package cn.wandersnail.ble.ota;

import static android.bluetooth.BluetoothGatt.GATT_SUCCESS;

import android.bluetooth.BluetoothAdapter;
import android.bluetooth.BluetoothDevice;
import android.bluetooth.BluetoothGatt;
import android.bluetooth.BluetoothGattCallback;
import android.bluetooth.BluetoothGattCharacteristic;
import android.bluetooth.BluetoothGattDescriptor;
import android.bluetooth.BluetoothManager;
import android.bluetooth.BluetoothProfile;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
import android.os.Build;
import android.os.Handler;
import android.os.Message;
import android.util.Log;
import android.widget.Toast;

import androidx.annotation.NonNull;
import androidx.annotation.RequiresApi;

import java.io.BufferedInputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.InputStream;
import java.util.UUID;

import cn.wandersnail.ble.Connection;
import cn.wandersnail.ble.ConnectionState;
import cn.wandersnail.ble.Device;
import cn.wandersnail.ble.EasyBLE;
import cn.wandersnail.ble.EventObserver;
import cn.wandersnail.ble.Request;

public class OTACore{
    private static final String TAG = "OTACore";
    private Context context;
    private final static String UUID_SEND_DATA = "0000ff01-0000-1000-8000-00805f9b34fb";
    private final static String UUID_RECV_DATA = "0000ff02-0000-1000-8000-00805f9b34fb";
    private final static String UUID_SERVICE_DATA_H = "02f00000-0000-0000-0000-00000000fe00";
    private final static String UUID_SEND_DATA_H = "02f00000-0000-0000-0000-00000000ff01";
    private final static String UUID_RECV_DATA_H = "02f00000-0000-0000-0000-00000000ff02";
    private final static String UUID_DES = "00002902-0000-1000-8000-00805f9b34fb";
    private final static int OTA_CMD_NVDS_TYPE = 0;
    private final static int OTA_CMD_GET_STR_BASE = 1;
    private final static int OTA_CMD_PAGE_ERASE = 3;
    private final static int OTA_CMD_CHIP_ERASE = 4;
    private final static int OTA_CMD_WRITE_DATA = 5;
    private final static int OTA_CMD_READ_DATA = 6;
    private final static int OTA_CMD_WRITE_MEM = 7;
    private final static int OTA_CMD_READ_MEM = 8;
    private final static int OTA_CMD_REBOOT = 9;
    private final static int OTA_CMD_NULL = 10;
    private final static int DEVICE_8010 = 0;
    private final static int DEVICE_8010H = 1;

    private String filePath;

    private boolean writeStatus = false;

    private int sencondaddr = 0x14000;
    private int firstaddr = 0;
    private int recv_data;
    private int writePrecent;
    private int delay_num;
    private long leng;
    private byte[] recvValue = null;
    public int mtuSize  = 247;
    public boolean mtuChange = false;
    private Handler mHandler;
    private InputStream input;
    private FileInputStream isfile = null;
    private WriterOperation woperation;
    private BluetoothGattCharacteristic mgattCharacteristic = null;
    private BluetoothGattDescriptor descriptor = null;
    private Connection connection;

    private OTACallback mCallback;

    public OTACore(Context context, String binFile) {
        this.context = context;
        filePath = binFile;
        mHandler = new MyHandler();
        woperation = new WriterOperation();
    }


    BluetoothGattCallback callback = new BluetoothGattCallback() {
        @Override
        public void onPhyUpdate(BluetoothGatt gatt, int txPhy, int rxPhy, int status) {
            super.onPhyUpdate(gatt, txPhy, rxPhy, status);
        }

        @Override
        public void onPhyRead(BluetoothGatt gatt, int txPhy, int rxPhy, int status) {
            super.onPhyRead(gatt, txPhy, rxPhy, status);
        }

        @Override
        public void onConnectionStateChange(BluetoothGatt gatt, int status, int newState) {
            super.onConnectionStateChange(gatt, status, newState);
            if (newState == BluetoothProfile.STATE_DISCONNECTED)
                mCallback.onDisconnected();

        }

        @Override
        public void onServicesDiscovered(BluetoothGatt gatt, int status) {
            super.onServicesDiscovered(gatt, status);
            if(status == GATT_SUCCESS){
                UUID UUID_SERVICE_H = UUID.fromString(UUID_SERVICE_DATA_H);
                UUID UUID_SEND_H = UUID.fromString(UUID_SEND_DATA_H);
                UUID UUID_RECV_H = UUID.fromString(UUID_RECV_DATA_H);
                try{
                    BluetoothGattCharacteristic gattCharacteristic = gatt.getService(UUID_SERVICE_H).getCharacteristic(UUID_SEND_H);
                    Log.d(TAG,"GATT uuid:"+gattCharacteristic.getUuid());
                    String uuidString = gattCharacteristic.getUuid().toString();
                    if(uuidString.equals(UUID_SEND_DATA_H)){
                        //setTitle("找到端口");
                        mgattCharacteristic = gattCharacteristic;
                        mHandler.sendEmptyMessage(5);//找到端口
                    }
                    gattCharacteristic = gatt.getService(UUID_SERVICE_H).getCharacteristic(UUID_RECV_H);
                    uuidString = gattCharacteristic.getUuid().toString();
                    if(uuidString.equals(UUID_RECV_DATA_H)){

                        descriptor = gattCharacteristic.getDescriptor(UUID.fromString(UUID_DES));
                        if (descriptor != null) {
                            connection.getGatt().setCharacteristicNotification(gattCharacteristic, true);

                            descriptor.setValue(BluetoothGattDescriptor.ENABLE_NOTIFICATION_VALUE);
                            connection.getGatt().writeDescriptor(descriptor);
                            //mHandler.sendEmptyMessage(6);//使能成功
                            mHandler.sendEmptyMessageDelayed(M_ID_DEVICE_CONNECTED, 2000);
                        }
                    }
                } catch(Exception e) {
                    mHandler.sendEmptyMessage(8);//未找到UUID
                }
            }
        }

        @Override
        public void onCharacteristicRead(BluetoothGatt gatt, BluetoothGattCharacteristic characteristic, int status) {
            super.onCharacteristicRead(gatt, characteristic, status);
        }

        @Override
        public void onCharacteristicWrite(BluetoothGatt gatt, BluetoothGattCharacteristic characteristic, int status) {
            super.onCharacteristicWrite(gatt, characteristic, status);
            if(status == 0){
                writeStatus = true;
            }
        }

        @Override
        public void onCharacteristicChanged(BluetoothGatt gatt, BluetoothGattCharacteristic characteristic) {
//            Log.e(TAG, "onCharacteristicChanged>>>>>>>>>>>>>>>>>>>>>>>>>>>>>");
            super.onCharacteristicChanged(gatt, characteristic);

            recvValue = characteristic.getValue();
            String s = formatHexString(recvValue, true);
            recv_data = 1;
//            Log.e(TAG, ">>>>>>>>>>>>"+recv_data+">>>>>>>>>>>>>>>"+recvValue+">>>>>>>>>>>>>"+s);
        }

        @Override
        public void onDescriptorRead(BluetoothGatt gatt, BluetoothGattDescriptor descriptor, int status) {
            super.onDescriptorRead(gatt, descriptor, status);
        }

        @Override
        public void onDescriptorWrite(BluetoothGatt gatt, BluetoothGattDescriptor descriptor, int status) {
            super.onDescriptorWrite(gatt, descriptor, status);
        }

        @Override
        public void onReliableWriteCompleted(BluetoothGatt gatt, int status) {
            super.onReliableWriteCompleted(gatt, status);
        }

        @Override
        public void onReadRemoteRssi(BluetoothGatt gatt, int rssi, int status) {
            super.onReadRemoteRssi(gatt, rssi, status);
        }

        @Override
        public void onMtuChanged(BluetoothGatt gatt, int mtu, int status) {
            super.onMtuChanged(gatt, mtu, status);
            System.out.println("onMtuChanged "+mtu + " " + status);
            if (GATT_SUCCESS == status) {
                mtuSize = mtu;
                System.out.println("BleService"+"onMtuChanged success MTU = " + mtu);
            }else {
                mtuSize = 235;
                Log.d("BleService", "onMtuChanged fail ");
            }
            mtuChange = true;
        }
    };

    public static String formatHexString(byte[] data, boolean addSpace) {
        if (data == null || data.length < 1)
            return null;
        StringBuilder sb = new StringBuilder();
        for (int i = 0; i < data.length; i++) {
            String hex = Integer.toHexString(data[i] & 0xFF);
            if (hex.length() == 1) {
                hex = '0' + hex;
            }
            sb.append(hex);
            if (addSpace)
                sb.append(" ");
        }
        return sb.toString().trim();
    }
    public void setOTACallback(OTACallback callback) {
        mCallback = callback;
    }

    public void setConnection(Connection connection){
        this.connection = connection;
        connection.setBluetoothGattCallback(callback);
    }
    public void startDownload(String filePath) {
        this.filePath = filePath;
        startDownload();
    }

    public void startDownload() {
        if (connection.getConnectionState() != ConnectionState.SERVICE_DISCOVERED) {
            mCallback.onError();
            Toast.makeText(context, "未连接", Toast.LENGTH_SHORT).show();
            return;
        }
        Log.i(TAG, "filePath = " + filePath);
        File file = new File(filePath);
        Log.i(TAG, "filePath = " + filePath + "; " + file.length());
        if (file.length() < 100) {
            mCallback.onError();
            Toast.makeText(context, "请选择有效的配置文件", Toast.LENGTH_SHORT).show();
            return;
        }
        mtuChange = false;
        mHandler.sendEmptyMessage(3);
        new Thread(new Runnable() {
            @RequiresApi(api = Build.VERSION_CODES.LOLLIPOP)
            @Override
            public void run() {
                try {
                    doSendFileByBluetooth(filePath);
                    //mHandler.sendEmptyMessage(1);
                } catch (FileNotFoundException  e) {
                    // TODO Auto-generated catch block
                    e.printStackTrace();
                }
            }
        }).start();
    }

    private int page_erase(int addr, long length) {

        long count = length / 0x1000;
        if ((length % 0x1000) != 0) {
            count++;
        }
        for (int i = 0; i < count; i++) {
            while (!woperation.send_data(OTA_CMD_PAGE_ERASE, addr, null, 0, connection, mgattCharacteristic)) {
                try {
                    Thread.sleep(50);
                    Log.d("TAG", "send_data error");
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
            delay_num = 0;
            while (!writeStatus) {
                delay_num++;
                if (delay_num % 8000 == 0) {
                    Log.d("TAG", "send_data once more");
                    woperation.send_data(OTA_CMD_PAGE_ERASE, addr, null, 0, connection, mgattCharacteristic);
                }
            }
            while (getRecv_data() != 1) ;
            setRecv_data(0);
            addr += 0x1000;
        }
        return 0;
    }

    public int getRecv_data() {
        return recv_data;
    }

    public void setRecv_data(int recv_data) {
        this.recv_data = recv_data;
    }

    boolean checkDisconnect() {
        if (connection == null || connection.getConnectionState() != ConnectionState.SERVICE_DISCOVERED) {
            mHandler.sendEmptyMessage(2);
            return true;
        }
        return false;
    }

    @RequiresApi(api = Build.VERSION_CODES.LOLLIPOP)
    public void doSendFileByBluetooth(String filePath)
            throws FileNotFoundException {
        if (!filePath.equals(null)) {
            mCallback.onStart();
            int read_count;
            int i = 0;
            int addr;
            int lastReadCount = 0;
            int packageSize = 235;//bleclass.mtuSize - 3; //235;
            int send_data_count = 0;
            int deviceType;

            File file = new File(filePath);// 成文件路径中获取文件
            isfile = new FileInputStream(file);
            leng = file.length();
            input = new BufferedInputStream(isfile);
            //crc 校验
            int fileCRC = 0;
            try {
                fileCRC = getCRC32new(filePath);
            } catch (Exception e) {
                mCallback.onError();
                e.printStackTrace();
            }
            //Log.d("TAG CRC",Integer.toHexString(fileCRC));
            setRecv_data(0);
            boolean result = woperation.send_data(OTA_CMD_NVDS_TYPE, 0, null, 0,
                    connection, mgattCharacteristic);
            Log.i(TAG, "result = "+result +">>>>>>>"+getRecv_data());
            while (getRecv_data() != 1) {
                if (checkDisconnect()) {
                    return;
                }
            }
            if ((woperation.bytetochar(recvValue) & 0x10) == 0) {
                deviceType = DEVICE_8010;
                connection.getGatt().requestMtu(247);
            } else {
                deviceType = DEVICE_8010H;
                connection.getGatt().requestMtu(512);
            }
            Log.e(TAG," connection.getMtu()="+connection.getMtu());
            while(mtuChange == false){
                try {
                    Thread.sleep(100);
                } catch (InterruptedException e) {
                    // TODO Auto-generated catch block
                    mCallback.onError();
                    e.printStackTrace();
                }
                System.out.println("mtuChange " + mtuChange);
            }
            packageSize = mtuSize - 3 - 9;
            byte[] inputBuffer = new byte[packageSize];
            setRecv_data(0);
            boolean result1 = woperation.send_data(OTA_CMD_GET_STR_BASE, 0, null, 0,
                    connection, mgattCharacteristic);
            Log.e(TAG,"result1="+result1+" getRecv_data="+getRecv_data());
            while (getRecv_data() != 1) {
                if (checkDisconnect()) {
                    return;
                }
            }
            if (deviceType == DEVICE_8010) {
                if (woperation.bytetoint(recvValue) == firstaddr) {
                    addr = sencondaddr;
                } else {
                    addr = firstaddr;
                }
            } else if (deviceType == DEVICE_8010H) {
                addr = woperation.bytetoint(recvValue);
            } else {
                return;
            }
            setRecv_data(0);
            page_erase(addr, leng);

            try {
                while (((read_count = input.read(inputBuffer, 0, packageSize)) != -1)) {
//    					woperation.send_data(OTA_CMD_WRITE_DATA, addr, inputBuffer,
//    							read_count, mgattCharacteristic, bleclass);
                    //20201116 修改
                    while (!woperation.send_data(OTA_CMD_WRITE_DATA, addr, inputBuffer,
                            read_count, connection, mgattCharacteristic)) {
                        try {
                            Thread.sleep(50);
                            Log.d("TAG", "send_data error");
                        } catch (InterruptedException e) {
                            mCallback.onError();
                            e.printStackTrace();
                        }
                    }
                    delay_num = 0;
                    while (!writeStatus) {
                        delay_num++;
                        if (delay_num % 8000 == 0) {
                            Log.d("TAG", "send_data once more");
                            woperation.send_data(OTA_CMD_WRITE_DATA, addr, inputBuffer, read_count, connection, mgattCharacteristic);
                        }
                    }
                    writeStatus = false;
                    //for(delay_num = 0;delay_num < 10000;delay_num++);
                    addr += read_count;
                    lastReadCount = read_count;
                    send_data_count += read_count;
                    //System.out.println("times" + i + " " + read_count);
                    i++;
                    if (writePrecent != (int) (((float) send_data_count / leng) * 100)) {
                        writePrecent = (int) (((float) send_data_count / leng) * 100);
                        mHandler.sendEmptyMessage(1);
                    }

                    while (getRecv_data() != 1) {
                        if (checkDisconnect()) {
                            return;
                        }
                    }
                    setRecv_data(0);
                }
                while (woperation.bytetoint(recvValue) != (addr - lastReadCount)) {
                    if (checkDisconnect()) {
                        return;
                    }
                }

                //woperation.send_data(OTA_CMD_REBOOT, 0, null, 0, mgattCharacteristic, bleclass);
                //crc 校验
                woperation.send_data_long(OTA_CMD_REBOOT, fileCRC, null, leng, connection, mgattCharacteristic);
                mHandler.sendEmptyMessage(0);
            } catch (IOException e) {
                mCallback.onError();
                e.printStackTrace();
            }

        } else {
            Toast.makeText(context, "请选择要发送的文件!",
                    Toast.LENGTH_LONG).show();
        }
    }

    private static int Crc32CalByByte(int oldcrc, byte[] ptr, int offset, int len) {
        int crc = oldcrc;
        int i = offset;
        while (len-- != 0) {
            int high = crc / 256; //取CRC高8位
            crc <<= 8;
            crc ^= crc_ta_8[(high ^ ptr[i]) & 0xff];
            crc &= 0xFFFFFFFF;
            i++;
        }
        return crc & 0xFFFFFFFF;
    }

    public static int getCRC32new(String fp) throws IOException {

        File file = new File(fp);// 成文件路径中获取文件
        FileInputStream isfile = null;
        try {
            isfile = new FileInputStream(file);

        } catch (FileNotFoundException e) {
            e.printStackTrace();
        }
        long leng = file.length();
        int read_count = 0;
        InputStream input = new BufferedInputStream(isfile);
        byte[] inputBuffer = new byte[256];
        int crcInit = 0;
        int couts = 0;
        while (((read_count = input.read(inputBuffer, 0, 256)) != -1)) {
            if (couts != 0) {
                crcInit = Crc32CalByByte(crcInit, inputBuffer, 0, read_count);
            }
            couts++;
            //Log.d("TAG CRC", "count: "+ couts+ "  "+ " read: "+ read_count+ "  "+ Integer.toHexString(crcInit));
        }
        return crcInit;
    }

    /* CRC 字节余式表 */
    private static final int crc_ta_8[] = new int[]{
            0x00000000, 0x77073096, 0xee0e612c, 0x990951ba,
            0x076dc419, 0x706af48f, 0xe963a535, 0x9e6495a3, 0x0edb8832,
            0x79dcb8a4, 0xe0d5e91e, 0x97d2d988, 0x09b64c2b, 0x7eb17cbd,
            0xe7b82d07, 0x90bf1d91, 0x1db71064, 0x6ab020f2, 0xf3b97148,
            0x84be41de, 0x1adad47d, 0x6ddde4eb, 0xf4d4b551, 0x83d385c7,
            0x136c9856, 0x646ba8c0, 0xfd62f97a, 0x8a65c9ec, 0x14015c4f,
            0x63066cd9, 0xfa0f3d63, 0x8d080df5, 0x3b6e20c8, 0x4c69105e,
            0xd56041e4, 0xa2677172, 0x3c03e4d1, 0x4b04d447, 0xd20d85fd,
            0xa50ab56b, 0x35b5a8fa, 0x42b2986c, 0xdbbbc9d6, 0xacbcf940,
            0x32d86ce3, 0x45df5c75, 0xdcd60dcf, 0xabd13d59, 0x26d930ac,
            0x51de003a, 0xc8d75180, 0xbfd06116, 0x21b4f4b5, 0x56b3c423,
            0xcfba9599, 0xb8bda50f, 0x2802b89e, 0x5f058808, 0xc60cd9b2,
            0xb10be924, 0x2f6f7c87, 0x58684c11, 0xc1611dab, 0xb6662d3d,
            0x76dc4190, 0x01db7106, 0x98d220bc, 0xefd5102a, 0x71b18589,
            0x06b6b51f, 0x9fbfe4a5, 0xe8b8d433, 0x7807c9a2, 0x0f00f934,
            0x9609a88e, 0xe10e9818, 0x7f6a0dbb, 0x086d3d2d, 0x91646c97,
            0xe6635c01, 0x6b6b51f4, 0x1c6c6162, 0x856530d8, 0xf262004e,
            0x6c0695ed, 0x1b01a57b, 0x8208f4c1, 0xf50fc457, 0x65b0d9c6,
            0x12b7e950, 0x8bbeb8ea, 0xfcb9887c, 0x62dd1ddf, 0x15da2d49,
            0x8cd37cf3, 0xfbd44c65, 0x4db26158, 0x3ab551ce, 0xa3bc0074,
            0xd4bb30e2, 0x4adfa541, 0x3dd895d7, 0xa4d1c46d, 0xd3d6f4fb,
            0x4369e96a, 0x346ed9fc, 0xad678846, 0xda60b8d0, 0x44042d73,
            0x33031de5, 0xaa0a4c5f, 0xdd0d7cc9, 0x5005713c, 0x270241aa,
            0xbe0b1010, 0xc90c2086, 0x5768b525, 0x206f85b3, 0xb966d409,
            0xce61e49f, 0x5edef90e, 0x29d9c998, 0xb0d09822, 0xc7d7a8b4,
            0x59b33d17, 0x2eb40d81, 0xb7bd5c3b, 0xc0ba6cad, 0xedb88320,
            0x9abfb3b6, 0x03b6e20c, 0x74b1d29a, 0xead54739, 0x9dd277af,
            0x04db2615, 0x73dc1683, 0xe3630b12, 0x94643b84, 0x0d6d6a3e,
            0x7a6a5aa8, 0xe40ecf0b, 0x9309ff9d, 0x0a00ae27, 0x7d079eb1,
            0xf00f9344, 0x8708a3d2, 0x1e01f268, 0x6906c2fe, 0xf762575d,
            0x806567cb, 0x196c3671, 0x6e6b06e7, 0xfed41b76, 0x89d32be0,
            0x10da7a5a, 0x67dd4acc, 0xf9b9df6f, 0x8ebeeff9, 0x17b7be43,
            0x60b08ed5, 0xd6d6a3e8, 0xa1d1937e, 0x38d8c2c4, 0x4fdff252,
            0xd1bb67f1, 0xa6bc5767, 0x3fb506dd, 0x48b2364b, 0xd80d2bda,
            0xaf0a1b4c, 0x36034af6, 0x41047a60, 0xdf60efc3, 0xa867df55,
            0x316e8eef, 0x4669be79, 0xcb61b38c, 0xbc66831a, 0x256fd2a0,
            0x5268e236, 0xcc0c7795, 0xbb0b4703, 0x220216b9, 0x5505262f,
            0xc5ba3bbe, 0xb2bd0b28, 0x2bb45a92, 0x5cb36a04, 0xc2d7ffa7,
            0xb5d0cf31, 0x2cd99e8b, 0x5bdeae1d, 0x9b64c2b0, 0xec63f226,
            0x756aa39c, 0x026d930a, 0x9c0906a9, 0xeb0e363f, 0x72076785,
            0x05005713, 0x95bf4a82, 0xe2b87a14, 0x7bb12bae, 0x0cb61b38,
            0x92d28e9b, 0xe5d5be0d, 0x7cdcefb7, 0x0bdbdf21, 0x86d3d2d4,
            0xf1d4e242, 0x68ddb3f8, 0x1fda836e, 0x81be16cd, 0xf6b9265b,
            0x6fb077e1, 0x18b74777, 0x88085ae6, 0xff0f6a70, 0x66063bca,
            0x11010b5c, 0x8f659eff, 0xf862ae69, 0x616bffd3, 0x166ccf45,
            0xa00ae278, 0xd70dd2ee, 0x4e048354, 0x3903b3c2, 0xa7672661,
            0xd06016f7, 0x4969474d, 0x3e6e77db, 0xaed16a4a, 0xd9d65adc,
            0x40df0b66, 0x37d83bf0, 0xa9bcae53, 0xdebb9ec5, 0x47b2cf7f,
            0x30b5ffe9, 0xbdbdf21c, 0xcabac28a, 0x53b39330, 0x24b4a3a6,
            0xbad03605, 0xcdd70693, 0x54de5729, 0x23d967bf, 0xb3667a2e,
            0xc4614ab8, 0x5d681b02, 0x2a6f2b94, 0xb40bbe37, 0xc30c8ea1,
            0x5a05df1b, 0x2d02ef8d,
    };

    void sendOtaWriteMEM() {
        byte[] bf = {0x2d, (byte) 0xe9, (byte) 0xf0, 0x47, 0x06, 0x46, 0x0c, 0x46, 0x17, 0x46, 0x44, (byte) 0xf6, (byte) 0x99, 0x08,
                0x20, 0x20, (byte) 0xff, (byte) 0xf7, 0x1f, (byte) 0xfb, (byte) 0x81, 0x46, 0x00, (byte) 0xf0, (byte) 0xdd, (byte) 0xf9, 0x00, (byte) 0xf0, 0x1e, (byte) 0xf8,
                0x00, 0x20, 0x00, (byte) 0xf0, 0x35, (byte) 0xfe, 0x0e, (byte) 0xe0, (byte) 0xb6, (byte) 0xf5, (byte) 0x80, 0x1f, 0x0b, (byte) 0xd2, (byte) 0xc6, (byte) 0xf5,
                (byte) 0x80, 0x15, (byte) 0xa5, 0x42, 0x00, (byte) 0xd3, 0x25, 0x46, 0x3a, 0x46, 0x29, 0x46, 0x30, 0x46, (byte) 0xc0, 0x47,
                0x2e, 0x44, 0x2f, 0x44, 0x64, 0x1b, 0x00, 0x2c, (byte) 0xee, (byte) 0xd1, 0x01, 0x20, (byte) 0xff, (byte) 0xf7, 0x4e, (byte) 0xfa,
                0x48, 0x46, (byte) 0xff, (byte) 0xf7, 0x04, (byte) 0xfb, (byte) 0xbd, (byte) 0xe8, (byte) 0xf0, (byte) 0x87, 0x00, 0x00, 0x4e, 0x20, 0x03, 0x49,
                0x08, 0x70, 0x45, 0x20, 0x08, 0x70, 0x57, 0x20, 0x08, 0x70, 0x70, 0x47, 0x00, (byte) 0x80, 0x05, 0x50,};
        woperation.send_data(OTA_CMD_WRITE_MEM, 0x20001676, bf, bf.length, connection, mgattCharacteristic);
    }

    void sendOtaWriteflashErase() {
//		byte[] bf2 = {0x70, (byte)0xb5, 0x0d, 0x46, 0x06, 0x46, 0x44, (byte)0xf2, 0x75, 0x74, 0x72, (byte)0xb6, 0x00, (byte)0xf0,
//				(byte)0x9e, (byte)0xf9, 0x00, 0x20, 0x00, (byte)0xf0, (byte)0xf8, (byte)0xfd, 0x29, 0x46, 0x30, 0x46, (byte)0xa0, 0x47, 0x00, 0x20,
//				0x00, (byte)0xf0, (byte)0xbc, (byte)0xfd, 0x01, 0x20, (byte)0xff, (byte)0xf7, 0x1d, (byte)0xfa, 0x62, (byte)0xb6, 0x70, (byte)0xbd, 0x00, 0x00, };
        byte[] bf2 = {0x70, (byte) 0xb5, 0x0d, 0x46, 0x06, 0x46, 0x44, (byte) 0xf2, 0x75, 0x74, 0x72, (byte) 0xb6, 0x00, (byte) 0xf0,
                (byte) 0x9e, (byte) 0xf9, 0x01, 0x20, 0x00, (byte) 0xf0, (byte) 0xf8, (byte) 0xfd, 0x29, 0x46, 0x30, 0x46, (byte) 0xa0, 0x47, 0x01, 0x20,
                (byte) 0xff, (byte) 0xf7, 0x20, (byte) 0xfa, 0x62, (byte) 0xb6, 0x70, (byte) 0xbd};
        woperation.send_data(OTA_CMD_WRITE_MEM, 0x200016fe, bf2, bf2.length, connection, mgattCharacteristic);
    }


    private static final int M_ID_OTA_SUCCESS = 0;
    private static final int M_ID_OTA_PROGRESS = 1;
    private static final int M_ID_OTA_FAIL_DISCONNECT = 2;
    private static final int M_ID_OTA_START = 3;
    private static final int M_ID_DEVICE_FOUND = 4;
    private static final int M_ID_DEVICE_PORT_FOUND = 5;
    private static final int M_ID_DEVICE_CONNECTED = 6;
    private static final int M_ID_DEVICE_DISCONNECTED = 7;
    private static final int M_ID_DEVICE_UUID_NOT_FOUND = 8;

    private static final int M_ID_RESCAN = 9;

    private class MyHandler extends Handler {
        @Override
        public void handleMessage(Message msg) {

            switch (msg.what) {
                case M_ID_OTA_SUCCESS:
                    //Toast.makeText(context, "写入成功", Toast.LENGTH_SHORT).show();
                    if (mCallback != null) {
                        mCallback.onSuccess();
                    }
                    break;
                case M_ID_OTA_PROGRESS:
                    Log.i(TAG, "写入.." + writePrecent + "%");
                    if (mCallback != null) {
                        mCallback.onProgress(writePrecent);
                    }
                    break;
                case M_ID_OTA_FAIL_DISCONNECT:
                    //Toast.makeText(context, "连接断开", Toast.LENGTH_LONG).show();
                    if (mCallback != null) {
                        mCallback.onFail();
                    }
                    break;
                case M_ID_OTA_START:
                    //showDialog();
                    break;
                case M_ID_DEVICE_FOUND:
                    //showConnectingDialog();
                    if (mCallback != null) {
                        mCallback.onFOUND(connection.getDevice().getAddress());
                    }
                    break;

                case M_ID_DEVICE_PORT_FOUND:
                    break;
                case M_ID_DEVICE_CONNECTED:
                    Log.i(TAG, "已连接 名称:" + connection.getDevice().getName() + "地址:" + connection.getDevice().getAddress());
                    //Toast.makeText(context, "连接成功", Toast.LENGTH_SHORT).show();
                    if (mCallback != null) {
                        mCallback.onConnected();
                    }
                    break;
                case M_ID_DEVICE_DISCONNECTED: {
                    //Toast.makeText(context, "断开连接", Toast.LENGTH_LONG).show();
                    if (mCallback != null) {
                        mCallback.onDisconnected();
                    }
                }
                break;

                case M_ID_DEVICE_UUID_NOT_FOUND: {
                    Toast.makeText(context, "未找到OTA所用UUID", Toast.LENGTH_LONG).show();
                    connection.disconnect();
                }
                break;
                case M_ID_RESCAN:
                    break;
                default:
                    break;
            }
        }
    }
}
